package belf.migrate.evaluate.helper;

import belf.migrate.api.table.schema.AbstractJdbcCatalog;
import belf.migrate.api.taskconf.JobContext;
import belf.migrate.evaluate.model.EvaluateGrammarResult;
import belf.migrate.evaluate.model.EvaluateObjectsResult;
import belf.migrate.evaluate.type.GrammarType;
import belf.migrate.evaluate.type.PageType;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 语法评估
 */
@Slf4j
public class EvaluateGrammarTool {

    protected JobContext jobContext;

    private final AbstractJdbcCatalog catalog;

    private final EvaluateObjectsResult objectsResult;

    private final int totalScore;

    public EvaluateGrammarTool(JobContext jobContext, EvaluateObjectsResult objectsResult, int totalScore) {
        this.jobContext = jobContext;
        this.catalog = jobContext.getSourceCatalog();
        this.objectsResult = objectsResult;
        this.totalScore = totalScore;
    }

    public EvaluateGrammarResult run() {

        EvaluateGrammarResult result = new EvaluateGrammarResult();
        Map<String, List<String>> riskItemsMap = new HashMap<>();
        Map<String, Double> socresMap = new HashMap<>();

        String taskType = jobContext.getTaskConf().getTaskType();
        String sourceCatalogName = null;
        if (taskType.contains("-")) {
            sourceCatalogName = taskType.split("-")[0];
        }

        for (String sinkCatalogName : jobContext.getTaskConf().getEvaluateConf().getSinkDbs()) {
            int tempScore = totalScore;
            List<String> riskItems = new ArrayList<>();
            //源数据库是否开启审计日志
            if (!catalog.isAuditLog()) {
                tempScore -= 3;
                riskItems.add("源数据库未开启审计日志，可能对迁移有一定影响！");
            }

            // 源数据库和目标数据库分页方式
            PageType pageType = PageType.getPageType(sourceCatalogName, sinkCatalogName);
            if (pageType != null) {
                tempScore -= 3;
                riskItems.add(pageType.getDesc());
            }

            //分析源库和目标库可能不兼容的语法
            Map<String, Set<GrammarType>> grammarTypesMap = objectsResult.getGrammarTypes();
            if (grammarTypesMap != null && grammarTypesMap.get(sinkCatalogName) != null) {
                for (GrammarType grammarType : grammarTypesMap.get(sinkCatalogName)) {
                    tempScore -= 1;
                    riskItems.add(grammarType.getDesc());
                }
            }
            int score = Math.max(tempScore, 0);
            socresMap.put(sinkCatalogName, (double) score / 100);
            riskItemsMap.put(sinkCatalogName, riskItems);
        }

        result.setRiskItems(riskItemsMap);
        result.setCompatiblePercent(socresMap);
        return result;
    }
}
